from django.shortcuts import render

# Create your views here.

# GET /oauth/qq/authorization/?next = xxx
from rest_framework import status
from rest_framework.generics import GenericAPIView, CreateAPIView
from rest_framework.response import Response
from rest_framework.views import APIView

from cart.utils import merge_cookie_cart_to_redis
from oauth.exceptions import QQAPIError
from oauth.models import OAuthQQUser
from oauth.serializers import QQAuthUserSerializer
from oauth.utils import OAuthQQ


# 返回QQ登录地址
class QQAuthURLView(APIView):
    '''
    QQ登录的网址
    '''

    def get(self, requset):
        '''
        :param requset:
        1. 获取next参数
        2. 拼接请求QQ的登录的网址&参数
        3. 返回QQ登录网址
        '''
        # 1. 获取next参数
        next = requset.query_params.get("next", '/')
        # 2. 拼接请求QQ的登录的网址&参数
        oauth = OAuthQQ(state=next)
        login_url = oauth.get_login_url()
        # 3. 返回QQ登录网址

        return Response({'login_url': login_url})


# QQ回调处理  获取open_id
# API: GET /oauth/qq/user/?code=<code>
class QQAuthUserView(CreateAPIView):
    serializer_class = QQAuthUserSerializer

    def post(self, request, *args, **kwargs):
        #   添加调用合并购物车函数
        #     1. 调用父类方法
        response = super().post(request, *args, **kwargs)

        #     2. 从create中获取user
        user = self.user
        merge_cookie_cart_to_redis(request, user, response)

        return response
        #     3. 调用合并购物车函数
        #     4. 返回响应 username, userid, token
        # def post(self, request, *args, **kwargs):
        #     '''
        #     保存绑定QQ的数据
        #     1. 获取数据 校验数据完整性, 手机号格式, 短信验证码, access_token 的有效性
        #     2. 保存用户数据,绑定数据, 签发 JWT token
        #     3. 返回响应 username, userid, token
        #     '''
        #
        #     # 1. 获取数据 校验数据完整性, 手机号格式, 短信验证码, access_token 的有效性
        #
        #     # 2. 保存用户数据,绑定数据, 签发 JWT token
        #     serializer = self.get_serializer(data=request.data)
        #     serializer.is_valid(raise_exception=True)
        #     serializer.save()
        #     # 3. 返回响应 username, userid, token
        #
        #     return Response(serializer.data, status=status.HTTP_201_CREATED)

    def get(self, request):
        '''
        # 1. 通过code 取到 access_token
        # 2. 在通过access_token取到open_id
        # 3. 利用open_id判断user是否注册
        # 4. 没有注册返回user为none, openid加密返回
        # 5. 注册了 生成token,返回user_name ,user_id , token,
        '''
        # 1. 通过code 取到 access_token
        # 获取code
        code = request.query_params.get('code')
        # 校验code
        if code is None:
            return Response({'message': '缺少参数code'}, status=status.HTTP_400_BAD_REQUEST)

        oauth = OAuthQQ()
        try:
            access_token = oauth.get_access_token(code=code)

            # 2. 在通过access_token取到open_id
            openid = oauth.get_openid(access_token=access_token)
        except QQAPIError:
            return Response({'message': 'qq登录异常'}, status=status.HTTP_503_SERVICE_UNAVAILABLE)

        # 3. 利用open_id判断user是否注册
        try:
            QQ_user = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            # 4. 没有注册返回user为none,openid加密返回
            token = oauth.generate_save_user_token(openid)
            return Response({'access_token': token})

        else:
            # 5. 注册了 生成token,返回user_name ,user_id , token,
            user = QQ_user.user
            # 服务器生成jwt 保存用户数据
            from rest_framework_jwt.settings import api_settings
            # 生成载荷
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            # 生成JWT token
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

            payload = jwt_payload_handler(user)
            print(payload)
            token = jwt_encode_handler(payload)

            user.token = token

            data = {
                "username": user.username,
                "user_id": user.id,
                "token": token
            }
            #   添加调用合并购物车函数

            response = Response(data)

            merge_cookie_cart_to_redis(request, user, response)

            return response
